package gui;

import javax.swing.JFrame;

import com.jgoodies.forms.layout.FormLayout;
import com.jgoodies.forms.layout.ColumnSpec;
import com.jgoodies.forms.layout.RowSpec;
import com.jgoodies.forms.factories.FormFactory;

import javax.swing.JLabel;
import javax.swing.SwingConstants;

import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;

import javax.swing.DefaultListModel;
import javax.swing.JPanel;
import javax.swing.JButton;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.ListSelectionModel;
import javax.swing.border.TitledBorder;
import javax.swing.BoxLayout;

import java.awt.Component;

import javax.swing.Box;
import javax.swing.ImageIcon;

import types.DataSet;

import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;


public class OutputWindow extends JFrame implements Printable  {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private JList<?> listTests;
	private static int[] pageBreaks;  // array of page break line positions.
	private static String[] testsNames;
	private static int ind=0;
    
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public OutputWindow(final DataSet finalDataSet, final String path) {
		
		testsNames = new String[finalDataSet.getSize()];
		
		JFrame guiOutFrame = new JFrame();
		guiOutFrame.setIconImage(Toolkit.getDefaultToolkit().getImage(OutputWindow.class.getResource("/images/OutputWin16.gif")));
		guiOutFrame.setAlwaysOnTop(true);
		guiOutFrame.setResizable(false);
        
        // frame properties
		guiOutFrame.setTitle("Restricted regression set");
		guiOutFrame.setSize(560,500);
        
        // center the JFrame in the middle of the screen
		guiOutFrame.setLocationRelativeTo(null);
		final DefaultListModel listValues = new DefaultListModel();
		guiOutFrame.getContentPane().setLayout(new FormLayout(new ColumnSpec[] {
				ColumnSpec.decode("56px"),
				FormFactory.RELATED_GAP_COLSPEC,
				ColumnSpec.decode("428px"),
				ColumnSpec.decode("max(52dlu;default)"),},
			new RowSpec[] {
				RowSpec.decode("26px"),
				RowSpec.decode("22px"),
				FormFactory.DEFAULT_ROWSPEC,
				FormFactory.RELATED_GAP_ROWSPEC,
				FormFactory.DEFAULT_ROWSPEC,
				FormFactory.RELATED_GAP_ROWSPEC,
				RowSpec.decode("333px"),
				RowSpec.decode("7px"),
				FormFactory.DEFAULT_ROWSPEC,
				FormFactory.RELATED_GAP_ROWSPEC,
				RowSpec.decode("34px"),
				RowSpec.decode("25px"),}));
		
		JLabel lblSubGroupsResult = new JLabel("Restricted regression set");
		lblSubGroupsResult.setIcon(new ImageIcon(OutputWindow.class.getResource("/images/output16.png")));
		lblSubGroupsResult.setFont(new Font("Tahoma", Font.BOLD, 18));
		lblSubGroupsResult.setHorizontalAlignment(SwingConstants.CENTER);
		lblSubGroupsResult.addMouseListener(new MouseAdapter()  {  
		    public void mouseClicked(MouseEvent e)  {  
		    	getMatrixEvent(finalDataSet);
		    }  
		}); 
		guiOutFrame.getContentPane().add(lblSubGroupsResult, "3, 2, center, center");
		
		final JPanel panelTests = new JPanel();
		
		panelTests.setBorder(new TitledBorder(null, "", TitledBorder.LEADING, TitledBorder.TOP, null, null));
		guiOutFrame.getContentPane().add(panelTests, "3, 7, 1, 3, fill, top");
		
		Boolean outliers_flg = false;
		for(int i=0	; i<finalDataSet.getFinalTests().size()	; i++)
		{
			int s = finalDataSet.getFinalTests().get(i).getSet();
			int t = finalDataSet.getFinalTests().get(i).getIndex(finalDataSet);
			
			if(s!=i)	outliers_flg = true;	// outliers 
			
			if(!outliers_flg)
			{
				listValues.addElement("sg"+(s+1)+"_test"+(t+1)+"   ");
				testsNames[ind++] = "sg"+(s+1)+"_test"+(t+1);
			}
			else
			{
				listValues.addElement("outlier"+"_test"+(t+1)+"   ");
				testsNames[ind++] = "out"+"_test"+(t+1);
			}
		}
		
		panelTests.setLayout(new BoxLayout(panelTests, BoxLayout.X_AXIS));
		
		listTests = new JList(listValues);	// add values to list
		listTests.setLayoutOrientation(JList.VERTICAL_WRAP);
		listTests.setFont(new Font("Tahoma", Font.PLAIN, 12));
		listTests.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		listTests.setVisibleRowCount(10);	
		listTests.addMouseListener(new MouseAdapter() {
		    public void mouseClicked(MouseEvent evt) {
		        JList list = (JList)evt.getSource();
		        if (evt.getClickCount() == 2) {	// 2-clicks
		            int index = list.locationToIndex(evt.getPoint());
		            
		            // open new frame
		            JFrame newFrame = new JFrame(list.getSelectedValue().toString());
		            JPanel panel = new JPanel();
		            
		            newFrame.setSize(400, 300);
		            newFrame.getContentPane().add(panel);
		            
		            JTextArea ta = new JTextArea(finalDataSet.getFinalTests().get(index).getTest(),2,60);
		            ta.setWrapStyleWord(true); 
		            panel.add(new JScrollPane(ta));

		            newFrame.setAlwaysOnTop(true);
		            newFrame.pack();
		            newFrame.setVisible(true);
		        }
		    }
		});
		panelTests.add(new JScrollPane(listTests));
		
		JPanel panelButtons = new JPanel();
		guiOutFrame.getContentPane().add(panelButtons, "3, 12, center, bottom");
		panelButtons.setLayout(new BoxLayout(panelButtons, BoxLayout.X_AXIS));
		
		JButton btnPrintResults = new JButton("Print results ");
		btnPrintResults.setIcon(new ImageIcon(OutputWindowSubGroups.class.getResource("/images/print16.gif")));
		 
		final PrinterJob job = PrinterJob.getPrinterJob();
        job.setPrintable(this);
        
		btnPrintResults.addActionListener(new ActionListener() { 
			public void actionPerformed(ActionEvent e) {
		         boolean ok = job.printDialog();
		         if (ok) {
		             try {
		                  job.print();              
		             } catch (PrinterException ex) {
		              /* The job did not successfully complete */
		             }
		         }
		    } 
        });
		
		
		panelButtons.add(btnPrintResults);
		
		Component horizontalStrut = Box.createHorizontalStrut(20);
		panelButtons.add(horizontalStrut);
		
		JButton btnSaveToFile = new JButton("Save results to file");
		btnSaveToFile.setIcon(new ImageIcon(OutputWindowSubGroups.class.getResource("/images/disk16.gif")));
		btnSaveToFile.addActionListener(new ActionListener() { 
			public void actionPerformed(ActionEvent e) {
				PrintWriter writer = null;
				try {
					writer = new PrintWriter(path+"\\Restricted_Set.txt", "UTF-8");
					
				} catch (FileNotFoundException | UnsupportedEncodingException e1) {
					e1.printStackTrace();
				}
				Boolean outliers_flg = false;
				for(int j=0	; j<finalDataSet.getFinalTests().size()	; j++)
				{
					int s = finalDataSet.getFinalTests().get(j).getSet();
					int t = finalDataSet.getFinalTests().get(j).getIndex(finalDataSet);
					
					if(s!=j)	outliers_flg = true;	// outliers 
					
					if(!outliers_flg){
						writer.println("sg"+(s+1)+"_test"+(t+1)+"   ");
						writer.println(finalDataSet.getFinalTests().get(j).getTest());
						writer.println();
					}
					else{
						writer.println("outlier"+"_test"+(t+1)+"   ");
						writer.println(finalDataSet.getFinalTests().get(j).getTest());
						writer.println();
					}
				}
				writer.println();
				writer.close();
		    } 
		});
		panelButtons.add(btnSaveToFile);
		      
        //make sure the JFrame is visible
		guiOutFrame.setVisible(true);

	}
	
	
	public void getMatrixEvent(final DataSet fds)
	{
		double[][] data = fds.getDistanceMatrix();
		double[][] d = new double[data.length+1][data.length+1];
		String[] h = new String[data.length+1];
		
		// headers
		for(int i=0; i<d.length; i++)	
		{
		
			if(i==0)	
			{
				h[i] = "test #";
				continue;
			}
			
			h[i] = testsNames[i-1]; 	// test num
		}
		
		// data
		for(int i=0; i<d.length; i++)	// rows
		{
			for(int j=0; j<d.length; j++)	// cols
			{
				if(i==0)
					d[i][j] = 0;	// init row[0]=0
				else
				{
					if((i-1)<data.length && (j)<data.length)
						d[i][j] = data[i-1][j];
				}
				
			}
		}

		MatrixWindow mw = new MatrixWindow(d,h,"medoids"); 
		mw.setVisible(true);
	}
	
	public int print(Graphics g, PageFormat pf, int pageIndex) throws PrinterException {
		Font font = new Font("Tahoma", Font.PLAIN, 12);
		FontMetrics metrics = g.getFontMetrics(font);
		int lineHeight = metrics.getHeight();

		if (pageBreaks == null) {
			int linesPerPage = (int)(pf.getImageableHeight()/lineHeight);
			int numBreaks = listTests.getModel().getSize() / linesPerPage;
			pageBreaks = new int[numBreaks];
			
			for (int b=0; b<numBreaks; b++) {
				pageBreaks[b] = (b+1)*linesPerPage;
			}
		}

		if (pageIndex > pageBreaks.length) {
			return NO_SUCH_PAGE;
		}
		
		Graphics2D g2d = (Graphics2D)g;
		g2d.translate(pf.getImageableX(), pf.getImageableY());

	int y = 0; 
	int start = (pageIndex == 0) ? 0 : pageBreaks[pageIndex-1];
	int end = (pageIndex == pageBreaks.length) ? listTests.getModel().getSize() : pageBreaks[pageIndex];
	
	for (int line=start; line<end; line++) {
		y += lineHeight;
		
		g.drawString(listTests.getModel().getElementAt(line).toString(), 0, y);
	}
	
	return PAGE_EXISTS;
		
	}
	
//	print one page only!!!	
//	public int print(Graphics g, PageFormat pf, int page) throws	PrinterException {
//		
//		if (page > 0) { /* We have only one page, and 'page' is zero-based */
//			return NO_SUCH_PAGE;
//		}
//		
//		/* User (0,0) is typically outside the imageable area, so we must
//		* translate by the X and Y values in the PageFormat to avoid clipping
//		*/
//		Graphics2D g2d = (Graphics2D)g;
//		g2d.translate(pf.getImageableX(), pf.getImageableY());
//		
//		/* Now print the lists  */
//		listTests.setLayoutOrientation(JList.VERTICAL_WRAP);
//		listTests.setVisibleRowCount(40);
//		listTests.print(g);
//		listTests.setLayoutOrientation(JList.HORIZONTAL_WRAP);
//		listTests.setVisibleRowCount(10);
//		
//		/* tell the caller that this page is part of the printed document  */
//		return PAGE_EXISTS;
//	}
		

}
